﻿using EventModel;
using Newtonsoft.Json;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace EventModel
{
    public class ExamTool
    {
        /// <summary>
        /// 保存双评题打分
        /// </summary>
        /// <param name="json"></param>
        public void SaveDouble(string json)
        {
            List<dynamic> list = JsonConvert.DeserializeObject<List<dynamic>>(json);
            if (list == null || list.Count == 0)
            {
                return;
            }
            long examid = list[0].test_id;//试卷ID
            long pid = list[0].pid;//项目ID
            string topic_number = list[0].topic_number;//试题题号
            //long id = 0;//学生得分明细表的主键ID
            string student_id = list[0].student_id;
            string teacher_id = list[0].teacher_id;
            string subject_id = list[0].subject_id;
            decimal arbitration_score = 0;//仲裁分数
            bool isExistDouble = false;
            decimal preScore = 0;//上个老师的评分
            decimal thisScore = list[0].score;

            SugarBase.Exec(db =>
            {
                var listTopic = db.Queryable<prpjects_paper_info>().Where(a => a.paper_id == examid).Where(a => a.topic_number == topic_number).ToList();
                arbitration_score = listTopic[0].arbitration_score;
                //查询是否存在此考生的平分记录
                var listDouble = db.Queryable<exam_double>().Where(a => a.studentid == student_id).Where(a => a.paper_id == examid).ToList();
                if (listDouble != null && listDouble.Count > 0)
                {
                    isExistDouble = true;
                    preScore = listDouble[0].score;
                }

                //保存exam_double表中的数据
                exam_double model = new exam_double();
                model.studentid = student_id;
                model.pid = pid;
                model.paper_id = examid;
                model.score = thisScore;
                model.topic_number = topic_number;
                model.teacher_id = teacher_id;

                ////保存阅卷明细
                //marking_log log = new marking_log();
                //log.id = Common.SnowflakeTest.Instance.GetId();
                //log.student_id = student_id;
                //log.paper_id = examid;
                //log.teacher_id = teacher_id;
                //log.score = thisScore;
                //log.topic_number = topic_number;
                //log.subject_id = subject_id;
                //log.create_on = DateTime.Now;
                //log.modify_on = DateTime.Now;
                //log.create_by = teacher_id;
                //db.Insertable<marking_log>(log).ExecuteCommand();

                if (!isExistDouble)//如果不存在或者分数差小于等于仲裁分数，则插入数据
                {
                    db.Insertable<exam_double>(model).ExecuteCommand();
                }
                else
                {
                    if (System.Math.Abs(preScore - thisScore) <= arbitration_score)
                    {
                        decimal avgscore = Math.Round((preScore + thisScore) / 2, 1);//如果分数差小于等于仲裁分数，取两个分数的平均分保存
                        dynamic obj = new ExpandoObject();
                        obj.test_id = examid;
                        obj.topic_number = topic_number;
                        obj.student_id = student_id;
                        obj.score = thisScore;
                        obj.pid = pid;
                        obj.subject_id = subject_id;
                        //obj.teacher_id = "0";//设置teacher_id=0，SaveExam方法中不再保存阅卷明细信息
                        SaveExam(JsonConvert.SerializeObject(obj));
                    }
                    else//如果两个分数差大于仲裁分数，保存第二个老师改分的同时往仲裁表中写入数据
                    {
                        db.Insertable<exam_double>(model).ExecuteCommand();
                        exam_arbitration arbitration = new exam_arbitration();
                        arbitration.student_id = student_id;
                        arbitration.paper_id = examid;
                        arbitration.topic_number = topic_number;
                        arbitration.pid = pid;
                        db.Insertable<exam_double>(model).ExecuteCommand();
                    }
                }
            });

            //0.根据试卷ID、题号查询双评题最多相差的分数
            //1.从数据库中查询是否已经有其他老师保存的双评题分数
            //2.如果没有存在其他老师的打分，则把当前记录存储到数据库中
            //3.如果存在，根据两次打分的差，是否大于最大相差分数，不大于，取两个分数的平均数保存到学生分数明细表，并且把当前数据存储到双评打分表里
            //4.如果大于最大差分，把当前学生ID、试卷ID、题号存储到仲裁表中，等待下一个仲裁的流程
        }

        /// <summary>
        /// 仲裁打分
        /// </summary>
        private void ThridScore(string json)
        {
            //Dictionary<string, object> dict = new Dictionary<string, object>();
            //if (gameId != 0)
            //{
            //    dict.Add("@gameId", gameId);//双引号里的字段是你数据库中的字段名称
            //}
            //if (serverId != 0)
            //{
            //    dict.Add("@gameId", gameId);
            //}

            //SqlParameter[] parameters = { ()=> {
            //     foreach (var item in dict)
            //        {
            //               new SqlParameter(item.Key, item.Value);
            //        }
            // } };
        }

        /// <summary>
        /// 保存主观题分数
        /// 仲裁打分可以调用这个方法
        /// </summary>
        public void SaveExam(string json)
        {
            List<dynamic> list = JsonConvert.DeserializeObject<List<dynamic>>(json);
            if (list == null || list.Count == 0)
            {
                return;
            }
            long examid = list[0].paper_id;//试卷ID
            string topic_number = list[0].topic_number;//试题编号
            string subject_id = list[0].subject_id;
            long pid = list[0].pid;
            long id = 0;
            string student_id = list[0].student_id;
            string teacher_id = list[0].teacher_id;
            bool isExist = false;//数据库中是否有此考试的分值信息
            //根据试卷ID和学生ID从数据库查询 是否存在以及改过的题目信息
            SugarBase.Exec(db =>
            {
                List<QuestionItem> bag = new List<QuestionItem>();//线程安全的集合
                decimal sumScore = 0;//总分，累计结果

                var listScore = db.Queryable<examination_topic>().Where(a => a.test_id == examid).Where(a => a.student_id == student_id).ToList();

                if (listScore != null && listScore.Count > 0)
                {
                    decimal temScore = 0;
                    if (!string.IsNullOrEmpty(listScore[0].student_cord))
                    {
                        var listQuestionItem = JsonConvert.DeserializeObject<List<QuestionItem>>(listScore[0].student_cord);
                        listQuestionItem.ForEach((t) =>
                        {
                            if (t.topic_number == topic_number)//如果是回评,已经存在此学生此题目的答题信息
                            {
                                temScore += Convert.ToDecimal(list[0].score) - t.score;
                                t.score = list[0].score;
                            }
                            bag.Add(t);
                        });
                    }
                    sumScore = listScore[0].student_score + temScore;
                    id = listScore[0].id;
                    isExist = true;
                }

                //判断是否为回评
                var ray = bag.Where(t => t.topic_number == topic_number).ToList();
                if (ray == null || ray.Count == 0)
                {
                    decimal score = list[0].score;
                    sumScore += score;
                    bag.Add(new QuestionItem() { topic_number = topic_number, answer = "", score = score });
                }

                ////保存阅卷明细
                //marking_log log = new marking_log();
                //log.id = Common.SnowflakeTest.Instance.GetId();
                //log.student_id = student_id;
                //log.paper_id = examid;
                //log.teacher_id = teacher_id;
                //log.score = list[0].score;
                //log.topic_number = topic_number;
                //log.subject_id = subject_id;
                //log.create_on = DateTime.Now;
                //log.modify_on = DateTime.Now;
                //log.create_by = teacher_id;
                //if (!teacher_id.Equals("0"))
                //{
                //    db.Insertable<marking_log>(log).ExecuteCommand();
                //}

                //计算总分，并把数据集保存到数据库
                decimal sum = sumScore;
                if (isExist)
                {
                    examination_topic model = listScore[0];
                    model.id = id;
                    model.student_score = sum;
                    model.student_cord = JsonConvert.SerializeObject(bag);
                    //保存总分和小题分数
                    string sql = $"update examination_topic set student_cord='{model.student_cord}',student_score={model.student_score} where id='{model.id}' and test_id='{model.test_id}'";
                    //db.Updateable(model).UpdateColumns(it => new { it.student_cord, it.student_score }).WhereColumns(it => new { it.id, it.test_id }).ExecuteCommand();
                    db.Ado.ExecuteCommand(sql);
                }
                else
                {
                    examination_topic model = new examination_topic();
                    model.id = SnowflakeTest.Instance.GetId();
                    model.pid = pid;
                    model.school_id = list[0].school_id;
                    model.class_id = list[0].class_id;
                    model.student_id = list[0].student_id;
                    model.subject_code = list[0].subject_code;
                    model.test_id = list[0].test_id;
                    model.student_cord = JsonConvert.SerializeObject(bag);
                    model.student_score = sum;
                    db.Insertable<examination_topic>(model).ExecuteCommand();
                }
            });
        }

        /// <summary>
        /// 保存选择题答题分数
        /// </summary>
        private void SaveScore(examination_topic json)
        {
            //1.参数json反序列化，此json保存的是一张试卷中该考生所有的选择题答案

            List<dynamic> list = JsonConvert.DeserializeObject<List<dynamic>>(json.student_cord);
            if (list == null || list.Count == 0)
            {
                return;
            }
            long examid = json.test_id;
            long pid = json.pid;
            long id = 0;
            string student_id = json.student_id;
            bool isExist = false;//数据库中是否有此考试的分值信息
            ConcurrentBag<QuestionItem> bag = new ConcurrentBag<QuestionItem>();//线程安全的集合
            ConcurrentBag<decimal> sumScore = new ConcurrentBag<decimal>();//总分，累计结果
            //根据试卷ID和学生ID从数据库查询 是否存在以及改过的题目信息
            SugarBase.Exec(db =>
            {
                var listScore = db.Queryable<examination_topic>().Where(a => a.test_id == examid).Where(a => a.student_id == student_id).ToList();
                var listAnswer = new RedisHelper().Item_Get<List<prpjects_paper_info>>($"answer.{examid}");
                if (listAnswer == null || listAnswer.Count == 0)
                {
                    listAnswer = db.Queryable<prpjects_paper_info>().Where(a => a.paper_id == examid).ToList();
                    new RedisHelper().Set<List<prpjects_paper_info>>($"answer.{examid}", listAnswer, TimeSpan.MaxValue);
                }
                if (listScore != null && listScore.Count > 0)
                {
                    if (!string.IsNullOrEmpty(listScore[0].student_cord))
                    {
                        var listQuestionItem = JsonConvert.DeserializeObject<List<QuestionItem>>(listScore[0].student_cord);
                        listQuestionItem.ForEach((t) =>
                        {
                            bag.Add(t);
                        });
                    }
                    sumScore.Add(listScore[0].student_score);
                    id = listScore[0].id;
                    isExist = true;
                }
                Parallel.ForEach(Partitioner.Create(0, list.Count), i =>
                {
                    for (int m = i.Item1; m < i.Item2; m++)
                    {
                        string topic_number = list[m].topic_number;//试题编号
                        string answer = list[m].answer;
                        int topic_kind = list[m].topic_kind;
                        decimal score = GetScore(listAnswer, topic_number, answer, topic_kind);
                        bag.Add(new QuestionItem() { topic_number = topic_number, answer = answer, score = score });
                        sumScore.Add(score);
                    }
                });
                //多线程循环完毕后，计算总分，并把数据集保存到数据库
                decimal sum = sumScore.Sum();
                if (isExist == true)
                {
                    examination_topic model = listScore[0];
                    model.id = id;
                    model.student_score = sum;
                    model.student_cord = JsonConvert.SerializeObject(bag);
                    //保存总分和小题分数
                    db.Updateable(model).UpdateColumns(it => new { it.student_cord, it.student_score }).WhereColumns(it => new { it.id, it.test_id }).ExecuteCommand();
                }
                else
                {
                    examination_topic model = new examination_topic();
                    model.id = SnowflakeTest.Instance.GetId();
                    model.pid = pid;
                    model.school_id = json.school_id;
                    model.class_id = json.class_id;
                    model.student_id = json.student_id;
                    model.subject_code = json.subject_code;
                    model.test_id = json.test_id;
                    model.student_cord = JsonConvert.SerializeObject(bag);
                    model.student_score = sum;
                    db.Insertable<examination_topic>(model).ExecuteCommand();
                }

            });


            //2.对反序列化后的list对象循环，做成任务并行的多线程循环，提高并发
            //3.单个循环里根据题号、试卷ID查询这道题的正确答案，比对正确答案给出分值
            //4.把打分的分值等信息Add到线程安全的集合中
            //5.如果此前有保存过的答题信息，需要加载出来读取到List集合中，再把新的答题信息Add到此集合中，然后update到数据库
        }

        /// <summary>
        /// 根据题型、题号、答案得到分值
        /// </summary>
        /// <param name="list"></param>
        /// <param name="topic_number"></param>
        /// <param name="answer"></param>
        /// <returns></returns>
        private decimal GetScore(List<prpjects_paper_info> list, string topic_number, string answer, int topic_kind)
        {
            decimal score = 0;
            var temp = list.Where(t => t.topic_number == topic_number).ToList();
            string answertemp = temp[0].answer;
            if (string.IsNullOrEmpty(answertemp))
            {
                new RedisHelper().Enqueue("ErrLog", $"试卷ID：{list[0].paper_id}---题号：{topic_number}，没有设置分数：");
            }
            decimal q_score = Convert.ToDecimal(temp[0].q_score);
            if (topic_kind == 0)
            {
                if (answertemp.ToUpper().Equals(answertemp.ToUpper()))
                {
                    return q_score;
                }
            }
            if (topic_kind == 1)
            {
                string referee_score = temp[0].referee_score;//多选题给分标准
                if (answertemp.ToUpper().Equals(answer.ToUpper()))
                {
                    return q_score;
                }
                else
                {
                    var dict = JsonConvert.DeserializeObject<Dictionary<object, string>>(referee_score);
                    if (dict == null || dict.Count == 0)
                    {
                        new RedisHelper().Enqueue("ErrLog", $"试卷ID：{list[0].paper_id}---题号：{topic_number}，没有设置分数：");
                        return score;
                    }
                    var item = dict.Where(t => t.Key.ToString().ToUpper().Equals(answer.ToUpper())).ToList();
                    if (item != null)
                        return Convert.ToDecimal(item[0].Value);
                }
            }
            return score;
        }
    }
}
